package com.google.code.jtasks.adapters;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import com.google.code.jtasks.connection.TaskRepoId;

/**
 * The default {@link IRepositoryMetadataProvider} implementation. It is safe for concurrent use, though
 * {@link ITaskSystemAdapter} implementors must be careful to ensure that their {@link RepositoryMetadata}
 * child objects are as well.
 */
public class RepositoryMetadataProviderImpl implements IRepositoryMetadataProvider
{
	private final ConcurrentMap<TaskRepoId, RepositoryMetadata<?, ?>> metadataMap;

	/**
	 * Constructs a new {@link RepositoryMetadataProviderImpl} instance.
	 */
	public RepositoryMetadataProviderImpl()
	{
		this.metadataMap = new ConcurrentHashMap<TaskRepoId, RepositoryMetadata<?, ?>>();
	}

	/**
	 * @see com.google.code.jtasks.adapters.IRepositoryMetadataProvider#getRepositoryMetadata(com.google.code.jtasks.connection.TaskRepoId)
	 */
	@Override
	public RepositoryMetadata<?, ?> getRepositoryMetadata(TaskRepoId taskRepoId)
	{
		// Create a new RepositoryMetadata to store in the map if there isn't one already there for this repo.
		RepositoryMetadata<?, ?> newRepoMetadata = new RepositoryMetadata<Object, Object>(taskRepoId);

		// The putIfAbsent method will either (a) return the current value if there is one for the repo or (b)
		// put the new one in and return null.
		RepositoryMetadata<?, ?> previousMapValue = metadataMap.putIfAbsent(taskRepoId, newRepoMetadata);

		// Return the already-there or new RepositoryMetadata instance
		if (previousMapValue != null)
			return previousMapValue;
		else
			return newRepoMetadata;
	}
}
